package com.vxdata.utils.modules.utils.case_8x;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.vxdata.common.utils.StringUtils;
import com.vxdata.common.utils.http.HttpUtils;
import com.vxdata.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 百度与高德逆地理编码
 * 经纬度 获取 位置信息
 */
@Component
@Slf4j
public class AddressUtils {
    @Autowired
    private ISysConfigService configService;

    @Value("${map.gaodeKey}")
    private String gaoDeKey = "d37f688a3f32a5a1b0b3aab7a1c0a378";
    @Value("${map.baiduKey}")
    private String baiduKey = "9XabKfDwU0bv0IEnsvpceR7i5wfmB92b";
    public static final String INFOCODE = "10000";
    /**
     * 使用百度服务
     */
    public static final String MAP_TYPE_BAIDU = "baidu";
    /**
     * 使用高德服务
     */
    public static final String MAP_TYPE_GAODE = "gaode";
    /**
     * 坐标系类型 : wgs84ll
     */
    public static final String COORD_TYPE_WGS84LL = "wgs84ll";
    /**
     * 坐标系类型 : gcj02ll
     */
    public static final String COORD_TYPE_GCJ02LL = "gcj02ll";


    /**
     * @param wd        纬度
     * @param jd        经度
     * @param coordtype 经纬度坐标系
     * @return
     */
    public HashMap<String, Object> getAddress(String wd, String jd, String coordtype) {
        if (StringUtils.isEmpty(jd) || StringUtils.isEmpty(wd)) {
            log.error("逆地理编码失败参数为空: lat:{}, jd:{}", wd, jd);
            return null;
        }
        // 使用高德地图还是百度地图 baidu 或 gaode
        String mapType = configService.selectConfigByKey("case.address.mapType");
        if (mapType.equals(MAP_TYPE_BAIDU)) {
            return baiDuAddress(wd, jd, coordtype);
        }
        return gaoDeAddress(wd, jd, coordtype);
    }

    /**
     * 高德地图你地理编码
     *
     * @param wd   纬度
     * @param jd   经度
     * @param type 经纬度坐标系格式
     * @return address:结构化地址信息, street:街道 ,roads:周边道路
     */
    private HashMap<String, Object> gaoDeAddress(String wd, String jd, String type) {
        HashMap<String, Object> map = new HashMap<>();
        try {
            String urlString;
            if (type.equals("wgs84ll")) {
                double lngDouble = Double.parseDouble(jd);
                double latDouble = Double.parseDouble(wd);
                double[] arrLongLat = GpsUtils.wgs84togcj02(lngDouble, latDouble);
                //参数解释: 纬度,经度 采用高德API可参考高德文档https://lbs.amap.com/
                urlString = "https://restapi.amap.com/v3/geocode/regeo?location=" + arrLongLat[0] + "," + arrLongLat[1] + "&extensions=all&batch=false&roadlevel=0&key=" + gaoDeKey;
            } else {
                urlString = "https://restapi.amap.com/v3/geocode/regeo?location=" + jd + "," + wd + "&extensions=all&batch=false&roadlevel=0&key=" + gaoDeKey;
            }
            String res = "";

            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("GET");
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                res += line + "\n";
            }
            in.close();

            //解析结果
            JSONObject jsonObject = JSONObject.parseObject(res);
            String infocode = jsonObject.getString("infocode");
            if (!StringUtils.equals(infocode, INFOCODE)) {
                log.error("get accidentAddr error, infocode:{}", infocode);
            }

            JSONObject jsonObject1 = jsonObject.getJSONObject("regeocode");
            // 结构化地址信息
            map.put("address", jsonObject1.getString("formatted_address"));
            // 街道
            String street = jsonObject1.getJSONObject("addressComponent").getJSONObject("streetNumber").getString("street");
            map.put("street", street);
            // 周边道路
            JSONArray jsonArr = new JSONArray(jsonObject1.getString("roads"));
            List<String> list = new ArrayList<>();
            for (int i = 0; i < jsonArr.size(); i++) {
                list.add(jsonArr.getJSONObject(i).getString("name"));
            }
            map.put("roads", list);
        } catch (Exception e) {
            log.error("get accidentAddr error,lng:{}, lat:{}, message:{}", jd, wd, e.getMessage());
            return null;
        }
        return map;
    }


    /**
     * 百度地图逆地理编码
     *
     * @param wd        纬度
     * @param jd        经度
     * @param coordtype 经纬度坐标系
     * @return
     */
    private HashMap<String, Object> baiDuAddress(String wd, String jd, String coordtype) {
        HashMap<String, Object> object = new HashMap<>();

        String location = wd + "," + jd;
        String url = "https://api.map.baidu.com/reverse_geocoding/v3/";
        String param = "ak=" + baiduKey + "&output=json&coordtype=" + coordtype + "&extensions_road=true&location=" + location;
        try {
            String res = HttpUtils.sendGet(url, param);
            JSONObject resObject = JSON.parseObject(res);
            if (!resObject.getString("status").equals("0")) {
                log.error("百度逆地理编码失败, 失败原因:{}", resObject);
                return null;
            }
            JSONObject result = resObject.getJSONObject("result");
            // 结构化地址信息
            object.put("address", result.getString("formatted_address"));
            // 街道
            object.put("street", result.getJSONObject("addressComponent").getString("street"));
            // 周边道路
            JSONArray jsonArr = new JSONArray(result.getString("roads"));
            List<String> list = new ArrayList<>();
            for (int i = 0; i < jsonArr.size(); i++) {
                list.add(jsonArr.getJSONObject(i).getString("name"));
            }
            object.put("roads", list);
        } catch (Exception e) {
            log.error("百度逆地理编码失败, 失败原因:{}", e.getMessage());
            e.printStackTrace();
        }
        return object;
    }


    public static void main(String[] args) {
        String wd = "31.26572950261027";
        String jd = "120.7272845548082";
        String coordtype = COORD_TYPE_GCJ02LL;
        AddressUtils addressUtils = new AddressUtils();
        HashMap<String, Object> map2 = addressUtils.getAddress(wd, jd, coordtype);
        System.out.println(map2);
    }
}